package com.mybatis.boost.generator.plugin;

import com.mybatis.boost.generator.plugin.adapter.MapperPluginAdapter;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.*;

import java.util.List;

/**
 * 动态表名插件
 *
 * @author jearton
 * @since 2016/12/12
 */
@Slf4j
public class DynamicTablePlugin extends MapperPluginAdapter {

    private FullyQualifiedJavaType iDynamicTableName;

    private FullyQualifiedJavaType transientAnnotation;

    private FullyQualifiedJavaType string;

    private boolean isFluentSetter;

    public DynamicTablePlugin() {
        super();
        iDynamicTableName = new FullyQualifiedJavaType("tk.mybatis.mapper.entity.IDynamicTableName"); //$NON-NLS-1$
        transientAnnotation = new FullyQualifiedJavaType("javax.persistence.Transient");
        string = new FullyQualifiedJavaType("String");
    }

    @Override
    public boolean validate(List<String> warnings) {
        try {
            isFluentSetter = Boolean.valueOf(properties.getProperty("fluentSetter", "false"));
            return true;
        } catch (Exception e) {
            log.error("DynamicTablePlugin properties parsing error", e);
            return false;
        }
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        implIDynamicTableName(topLevelClass, introspectedTable);
        return true;
    }

    @Override
    public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        implIDynamicTableName(topLevelClass, introspectedTable);
        return true;
    }

    @Override
    public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        implIDynamicTableName(topLevelClass, introspectedTable);
        return true;
    }

    private void implIDynamicTableName(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
        topLevelClass.addImportedType(iDynamicTableName);
        topLevelClass.addImportedType(transientAnnotation);
        topLevelClass.addSuperInterface(iDynamicTableName);

        Field field = new Field();
        field.setName("dynamicTableName"); //$NON-NLS-1$
        field.setType(string); //$NON-NLS-1$
        field.setVisibility(JavaVisibility.PRIVATE);
        field.addAnnotation("@Transient");
        context.getCommentGenerator().addFieldComment(field, introspectedTable);

        topLevelClass.addField(field);

        if (isFluentSetter) {
            Method fluentMethod = new Method();
            fluentMethod.setVisibility(JavaVisibility.PUBLIC);
            fluentMethod.setReturnType(topLevelClass.getType());
            fluentMethod.setName(field.getName());
            fluentMethod.addParameter(new Parameter(string, field.getName()));
            this.context.getCommentGenerator().addGeneralMethodComment(fluentMethod, introspectedTable);
            fluentMethod.addBodyLine("this." + field.getName() + " = " + field.getName() + ";");
            fluentMethod.addBodyLine("return this;");
            topLevelClass.addMethod(fluentMethod);
        }
    }
}
